﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.DataAccess.Common;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using Meta = T.FAS.Runtime.Metadata.Entity.DataModel;

namespace T.FAS.Runtime.DataAccess.Engine
{
    /// <summary>
    /// 对象属性值工具类
    /// </summary>
    class ObjectPropertyValueUtils
    {
        private static readonly IDACLogService s_localLogService = DACLogFactory.GetDACLogService();

        /// <summary>
        /// 从数据源中获取对应的value
        /// </summary>
        /// <param name="dataObject"></param>
        /// <param name="element"></param>
        /// <param name="dataColumn"></param>
        /// <param name="instance"></param>
        /// <param name="langKey"></param>
        /// <param name="i18NCode"></param>
        /// <returns></returns>
        public static object GetPropValue(DataObject dataObject, CompositeNodeObjectElement element, Meta.DataColumn dataColumn, object instance, string langKey = null, string i18NCode = null, bool isMask = false)
        {
            if (instance is DataRow dataRow) //DataRow一般为新增Create时的DTO结构
            {
                if (dataRow.Table == null || element == null)
                {
                    Exception ex = new FasException(DataAccessErrorCode.ORM.Error, "DataRow查找不到所属DataTable或Element为空");
                    s_localLogService.WriteError(ex);
                    throw ex;
                }
                if (dataColumn.IsInternational && !string.IsNullOrEmpty(langKey))
                {
                    string langFieldName = InternationalTools.GetRealFieldName(dataObject, dataColumn.ColumnName, langKey);
                    string langElementID = InternationalTools.GetDataItemElementIDKey(dataObject, element, langKey);
                    //string langElementID = InternationalTools.GetRealFieldName(dataObject, element.ID, langKey);
                    if (dataRow.Table.Columns.Contains(langFieldName)) //先查找物理列名
                    {
                        return dataRow[langFieldName];
                    }
                    else if (dataRow.Table.Columns.Contains(langElementID)) //然后查找element.id
                    {
                        return dataRow[langElementID];
                    }
                }
                //统一数据访问服务掩码改造：获取新增数据中的掩码数据
                if (MaskTool.EnableFASMaskStorage(dataColumn.MaskingRule) && isMask)
                {
                    string maskFieldName = Meta.DataColumn.GetMaskColumnName(dataObject, dataColumn.ColumnName);
                    string maskElementID = MaskTool.GetMaskDataItemElementIDKey(dataObject, element);
                    if (dataRow.Table.Columns.Contains(maskFieldName)) //先查找物理列名
                    {
                        return dataRow[maskFieldName];
                    }
                    else if (dataRow.Table.Columns.Contains(maskElementID)) //然后查找element.id
                    {
                        return dataRow[maskElementID];
                    }
                }
               
                if (dataRow.Table.Columns.Contains(dataColumn.ColumnName)) //先查找物理列名
                {
                    return dataRow[dataColumn.ColumnName];
                }
                else if (dataRow.Table.Columns.Contains(element.ID)) //然后查找element.id
                {
                    return dataRow[element.ID];
                }
                return null;
            }
            else if (instance is UpdateChangeSet changeSet) //ChangeSet为更新Update时的DTO结构
            {
                if (dataColumn.IsInternational && !string.IsNullOrEmpty(i18NCode))
                {
                    string logicFieldName = InternationalTools.GetLogicFieldName(dataColumn.ColumnName, i18NCode);
                    return changeSet.ChangeSetItems.FirstOrDefault(i => i.ColumnCode == logicFieldName)?.NewValue;
                }
                //统一数据访问服务掩码改造：获取更新数据中的掩码数据
                if (MaskTool.EnableFASMaskStorage(dataColumn.MaskingRule) && isMask)
                {
                    string maskFieldName = Meta.DataColumn.GetMaskColumnName(dataObject, dataColumn.ColumnName);
                    return changeSet.ChangeSetItems.FirstOrDefault(i => i.ColumnCode == maskFieldName)?.NewValue;
                }
                return changeSet.ChangeSetItems.FirstOrDefault(i => i.ColumnCode == dataColumn.ColumnName)?.NewValue;
            }
            else
            {
                return GetPropValue(element.PropertyName, instance);
            }
        }

        /// <summary>
        /// 尝试获取实体的值，优先转换为TRecord，然后尝试通过反射获取属性值
        /// </summary>
        /// <param name="propName"></param>
        /// <param name="instance"></param>
        /// <returns></returns>
        public static object GetPropValue(string propName, object instance)
        {
            if (instance is TRecord)
            {
                var record = instance as TRecord;
                return record.GetValue(propName);
            }

            var prop = instance.GetType().GetProperty(propName);
            if (prop == null)
            {
                Exception ex = new FasException(DataAccessErrorCode.ORM.NotFindProperty, "CompositeDataObject cannot find property! PropertyName: " + propName);
                s_localLogService.WriteError(ex);
                throw ex;
            }
            return prop.GetValue(instance);
        }

        public static IEnumerable<object> GetCollectionPropValue(string propName, object instance)
        {
            IEnumerable list = null;

            if (instance is TRecord)
            {
                var record = instance as TRecord;
                list = record.GetValue(propName) as IEnumerable;
            }
            else
            {
                var prop = instance.GetType().GetProperty(propName);
                list = prop.GetValue(instance) as IEnumerable;
            }

            var valueList = new List<object>();

            if (list == null) return valueList;

            foreach (var item in list)
            {
                valueList.Add(item);
            }

            return valueList;
        }

    }
}
